
import fse from 'fs-extra';
import http from 'http';
import https from 'https';
import pLimit from 'p-limit';
import path from 'path';
import properLockfile from 'proper-lockfile';
import { URL } from 'url';

// 初始化配置
const configPath = './server_save_audio_config.json';
const dataPath = './save_audio_data.json';
const downloadLimiter = pLimit(5);
const dirCache = new Set();

// 工具函数
const randomString = (length = 10) => {
  return Array.from({ length }, () =>
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
      .charAt(Math.floor(Math.random() * 62))).join('');
};

// 目录管理
const createMkdir = async () => {
  const now = new Date();
  const folderName = `${String(now.getMonth() + 1).padStart(2, '0')}_${String(now.getDate()).padStart(2, '0')}`;

  if (!dirCache.has(folderName)) {
    await fse.ensureDir(folderName);
    dirCache.add(folderName);
  }
  return folderName;
};

// 增强版下载器
const downloadFile = async (url, filePath, retries = 2) => {
  for (let i = 0; i <= retries; i++) {
    try {
      await new Promise((resolve, reject) => {
        const timeout = setTimeout(() =>
          reject(new Error(`Download timeout after 15s [${url}]`)), 15000);

        const protocol = new URL(url).protocol === 'http:' ? http : https;
        const file = fse.createWriteStream(filePath);

        protocol.get(url, res => {
          res.pipe(file)
            .on('finish', () => {
              clearTimeout(timeout);
              file.close(resolve);
            })
            .on('error', reject);
        }).on('error', reject);
      });
      return;
    } catch (err) {
      if (i === retries) throw err;
      await new Promise(r => setTimeout(r, 1000 * (i + 1)));
    }
  }
};

// 核心存储逻辑
const save_audio = async (url, text = '') => {
  if (!url?.trim()) return false;

  const release = await properLockfile.lock(dataPath);
  try {
    const [dataJson, folderPath] = await Promise.all([
      fse.readJson(dataPath).catch(() => ({})),
      createMkdir()
    ]);

    const filePath = path.join(folderPath, `${randomString()}.mp3`);
    console.log(`下载 ${url} -> ${filePath}`);

    await downloadLimiter(() => downloadFile(url, filePath));

    const targetData = dataJson[folderPath] || [];
    targetData.push({ path: filePath, text });

    const tmpPath = `${dataPath}.tmp`;
    await fse.writeJson(tmpPath,
      { ...dataJson, [folderPath]: targetData },
      { spaces: 2 }
    );
    await fse.rename(tmpPath, dataPath);
  } finally {
    await release();
  }
};

// HTTP服务
const startServer = async (port = 7777) => {
  const server = http.createServer(async (req, res) => {
    if (req.method === 'POST') {
      try {
        const body = await new Promise((resolve) => {
          let data = '';
          req.on('data', chunk => data += chunk);
          req.on('end', () => resolve(data));
        });

        const { audio, text } = JSON.parse(body);
        await save_audio(audio, text);

        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ success: true }));
      } catch (err) {
        res.writeHead(500, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: err.message }));
      }
    } else {
      res.writeHead(405, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ error: 'Method Not Allowed' }));
    }
  });

  server.listen(port, () => console.log(`Server running at http://localhost:${port}`));
};

// 启动服务
(async () => {
  const config = await fse.readJson(configPath).catch(() => ({}));
  startServer(config.port || 7777);
})();
